package com.suray.basic.wcs.path.core;


import com.suray.basic.wcs.path.enums.DirectionStatus;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.path.properties.PathProperties;
import com.suray.basic.wcs.utils.Action;
import com.suray.basic.wcs.utils.Coord;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

public class Route {

    private String district;
    /**
     * 路径起始位置
     */
    private Node startGrid;
    /**
     * 路径目的位置
     */
    private Node endGrid;
    /**
     * 所有经过节点集合
     */
    private List<Node> nodeList;
    /**
     * 段总数
     */
    private Integer segmentNum;

    /**
     * 该路径所消耗值
     */
    private Long cost;

    public Node getStartGrid() {
        return startGrid;
    }

    public void setStartGrid(Node startGrid) {
        this.startGrid = startGrid;
    }

    public Node getEndGrid() {
        return endGrid;
    }

    public void setEndGrid(Node endGrid) {
        this.endGrid = endGrid;
    }

    public Long getCost() {
        return cost;
    }

    public void setCost(Long cost) {
        this.cost = cost;
    }

    /**
     * 获取小车行驶参数
     *
     * @return
     */
    public void addNodeDirection() {
        List<Node> nodeList = getNodeList();
        if (!CollectionUtils.isEmpty(nodeList)) {
            for (int i = 0; i < nodeList.size() - 1; i++) {
                Node curNode = nodeList.get(i);
                Node nextNode = nodeList.get(i + 1);
                //  行驶方向
                getDriverParam(nextNode, curNode);
                //  终点行驶方向
                if (i == nodeList.size() - 2) {
                    nextNode.setDirection(curNode.getDirection());
                }
            }
        }
    }

    /**
     * 获取小车行驶参数
     *
     * @return
     */
    public List<NodeToRes> getMovePara() {
        List<NodeToRes> moveParaNodeToResList = new ArrayList<>();
        List<Node> nodeList = addActionForNodeList();
        // 添加换向动作
        for (int i = nodeList.size() - 1; i > 1; i--) {
            if ((Coord.isStraight(nodeList.get(i), nodeList.get(i - 1)) && !Coord.isStraight(nodeList.get(i), nodeList.get(i - 2))
                    && Coord.isStraight(nodeList.get(i - 1), nodeList.get(i - 2)))) {
                addActionXdOrPd(nodeList.get(i - 1), nodeList.get(i));
            }
            // 起点添加动作
            if (i == 2) {
                addActionXdOrPd(nodeList.get(i - 2), nodeList.get(i - 1));
            }
        }
        if (nodeList.size() == 2) {
            addActionXdOrPd(nodeList.get(0), nodeList.get(1));
        }
        return getNodeToRes(moveParaNodeToResList, nodeList);
    }

    /**
     * 节点集合转换成可发送给res的集合
     *
     * @param moveParaNodeToResList
     * @param nodeList
     * @return
     */
    private List<NodeToRes> getNodeToRes(List<NodeToRes> moveParaNodeToResList, List<Node> nodeList) {
        int segmentNum = 0;
        for (int i = 0; i < nodeList.size(); i++) {
            segmentNum++;
            Node node = nodeList.get(i);
            if (node.getResAction() != null) {
                segmentNum++;
            }
            moveParaNodeToResList.add(new NodeToRes(nodeList.get(i), segmentNum));
        }
        this.setSegmentNum(segmentNum);
        return moveParaNodeToResList;
    }

    /**
     * 节点中添加动作
     *
     * @return
     */
    private List<Node> addActionForNodeList() {
        List<Node> nodeList = getNodeList();
        // 为调用提升机添加动作
        for (int i = 0; i < nodeList.size() - 1; i++) {
            Node curNode = nodeList.get(i); // 当前节点
            Node nextNode = nodeList.get(i + 1); // 下一个节点
            if (nextNode.getNodeType().equals(NodeType.L)) {
                curNode.addActions(Action.ASSIGN_LIFTER);
                nextNode.addActions(Action.RGV_INSIDE_LIFTER);
            } else if (curNode.getNodeType().equals(NodeType.L)) {
                nextNode.addActions(Action.RGV_OUTSIDE_LIFTER);
            }
            // 当前节点是自动门，上一个节点添加请求开启自动门的动作，下一个节点添加请求关闭自动门的动作
            if (curNode.getIsDoor() != null && curNode.getIsDoor()) {
                Node lastNode = (i - 1 >= 0) ? nodeList.get(i - 1) : null;
                if (lastNode != null) {
                    lastNode.addActions(Action.ASSIGN_OPEN_DOOR);
                    nextNode.addActions(Action.ASSIGN_CLOSE_DOOR);
                }
            }
        }
        return nodeList;
    }

    /**
     * 获取小车行驶参数
     * 5代车
     *
     * @return
     */
    public List<NodeToRes> getMovePara(boolean palletUp) {
        List<NodeToRes> moveParaNodeToResList = new ArrayList<>();
        List<Node> nodeList = addActionForNodeList();
        // 添加换向动作
        for (int i = nodeList.size() - 1; i > 1; i--) {
            if ((Coord.isStraight(nodeList.get(i), nodeList.get(i - 1)) && !Coord.isStraight(nodeList.get(i), nodeList.get(i - 2))
                    && Coord.isStraight(nodeList.get(i - 1), nodeList.get(i - 2)))) {
                addActionXdOrPd(nodeList.get(i - 1), nodeList.get(i), palletUp);
            }
            // 起点添加动作
            if (i == 2) {
                addActionXdOrPd(nodeList.get(i - 2), nodeList.get(i - 1), palletUp);
            }
        }
        if (nodeList.size() == 2) {
            addActionXdOrPd(nodeList.get(0), nodeList.get(1), palletUp);
        }
        return getNodeToRes(moveParaNodeToResList, nodeList);
    }

    /**
     * 获取两点之间的行驶信息
     *
     * @param start 起点
     * @param end   终点
     * @return boolean
     */
    protected static void getDriverParam(Node end, Node start) {
        String direction = "";
        if (start.equals(end)) {
            // throw new IllegalArgumentException("起终点相同, 无法获取行驶数据");
        } else {
            if (start.getZ() != end.getZ()) {
                direction = end.getZ() + "";
            } else if (start.getY() == end.getY()) {// 巷道行驶
                if (start.getX() < end.getX()) {// 巷道正向行驶
                    direction = "x+";
                } else {// 巷道反向行驶
                    direction = "x-";
                }
            } else if (start.getX() == end.getX()) {
                if (start.getY() < end.getY()) {// 坡道正向行驶
                    direction = "y+";
                } else {// 坡道反向行驶
                    direction = "y-";
                }
            }
        }
        start.setDirection(direction);
    }

    public String getDistrict() {
        return district;
    }

    public List<Node> getNodeList() {
        return nodeList;
    }

    public void setNodeList(List<Node> nodeList) {
        this.nodeList = nodeList;
    }

    public void setDistrict(String district) {
        this.district = district;
    }

    public Integer getSegmentNum() {
        return segmentNum;
    }

    public void setSegmentNum(Integer segmentNum) {
        this.segmentNum = segmentNum;
    }

    /**
     * 给节点添加换向动作
     *
     * @param startNode
     * @param endNode
     */
    public void addActionXdOrPd(Node startNode, Node endNode) {
        if (PathProperties.RAMP_OR_WAY == DirectionStatus.XD_13) {
            if (startNode.getX() == endNode.getX()) {
                startNode.setResAction(Action.CHANGE_TO_RAMP);
            } else {
                startNode.setResAction(Action.CHANGE_TO_ROADWAY);
            }
        } else if (PathProperties.RAMP_OR_WAY == DirectionStatus.PD_24) {
            if (startNode.getX() == endNode.getX()) {
                startNode.setResAction(Action.CHANGE_TO_ROADWAY);
            } else {
                startNode.setResAction(Action.CHANGE_TO_RAMP);
            }
        } else {
            throw new RuntimeException("WcsProperties中的RAMP_OR_WAY参数配置错误");
        }
    }

    /**
     * 给节点添加换向动作
     *
     * @param startNode
     * @param endNode
     */
    public void addActionXdOrPd(Node startNode, Node endNode, boolean palletUp) {
        if (PathProperties.RAMP_OR_WAY == DirectionStatus.XD_13) {
            if (palletUp) {
                if (startNode.getDirection().contains("x") && !NodeType.P.equals(startNode)) {
                    //托盘顶升，执行顶升动作，顶升带动换向动作
                    startNode.setResAction(Action.PALLET_UP);
                } else {
                    startNode.setResAction(Action.CHANGE_TO_RAMP);
                }
            } else {
                if (startNode.getX() == endNode.getX()) {
                    startNode.setResAction(Action.CHANGE_TO_RAMP);
                } else {
                    startNode.setResAction(Action.CHANGE_TO_ROADWAY);
                }
            }
        } else if (PathProperties.RAMP_OR_WAY == DirectionStatus.PD_24) {
            if (palletUp) {
                if (startNode.getDirection().contains("y") && !NodeType.P.equals(startNode)) {
                    //托盘顶升，执行顶升动作，顶升带动换向动作
                    startNode.setResAction(Action.PALLET_UP);
                } else {
                    startNode.setResAction(Action.CHANGE_TO_RAMP);
                }
            } else {
                if (startNode.getX() == endNode.getX()) {
                    startNode.setResAction(Action.CHANGE_TO_ROADWAY);
                } else {
                    startNode.setResAction(Action.CHANGE_TO_RAMP);
                }
            }
        } else {
            throw new RuntimeException("WcsProperties中的RAMP_OR_WAY参数配置错误");
        }
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        nodeList.forEach(node -> stringBuilder.append(node.toString() + "," + (node.getResAction() == null ? "" : node.getResAction())));
        return "Route{" +
                ", startGrid=" + startGrid +
                ", endGrid=" + endGrid +
                ", nodeList=" + stringBuilder +
                ", segmentNum=" + segmentNum +
                ", cost=" + cost +
                '}';
    }
}
